#include<iostream>
#include<vector>
#include<string>
#include<memory>
#include"StrBlob.h"
using namespace std;
class StrBlobPtr{
friend bool operator==(const StrBlobPtr &sb1,const StrBlobPtr &sb2);
friend bool operator!=(const StrBlobPtr &sb1,const StrBlobPtr &sb2);
public:
	StrBlobPtr():curr(0){}
	StrBlobPtr(StrBlob &a,size_t sz=0):wptr(a.data),curr(sz){}
	string& deref()const;
	StrBlobPtr& incr();
	StrBlobPtr& operator++();
	StrBlobPtr& operator--();
	StrBlobPtr operator++(int);
	StrBlobPtr operator--(int);
	string& operator*() const;
	string* operator->() const;
	size_t get_curr(){return curr;}
private:
	shared_ptr<vector<string>> check(size_t,const string&)const;
	weak_ptr<vector<string>> wptr;
	size_t curr;
};
bool operator==(const StrBlobPtr &sb1,const StrBlobPtr &sb2);
bool operator!=(const StrBlobPtr &sb1,const StrBlobPtr &sb2);
shared_ptr<vector<string>> StrBlobPtr::check(size_t i,const string &msg)const
{
	auto ret=wptr.lock();
	if(!ret)
		throw runtime_error("unbound StrBlobPtr");
	if(i>=ret->size())
		throw out_of_range(msg);
	return ret;
}
StrBlobPtr& StrBlobPtr::operator++()
{
	check(curr,"increment past end of StrBlobPtr");
	++curr;
	return *this;
}
StrBlobPtr& StrBlobPtr::operator--()
{
	--curr;
	check(curr,"decrement past begin of StrBlobPtr");
	return *this;
}
StrBlobPtr StrBlobPtr::operator++(int)
{
	auto ret=*this;
	++*this;
	return ret;
}
StrBlobPtr StrBlobPtr::operator--(int)
{
	auto ret=*this;
	--*this;
	return ret;
}
string& StrBlobPtr::operator*() const
{
	auto p=check(curr,"dereference past end");
	return (*p)[curr];
}
string* StrBlobPtr::operator->() const
{
	return & this->operator*();
}
bool operator==(const StrBlobPtr &sb1,const StrBlobPtr &sb2)
{
	return (sb1.curr)==(sb2.curr);
}
bool operator!=(const StrBlobPtr &sb1,const StrBlobPtr &sb2)
{
	return !(sb1==sb2);
}
string& StrBlobPtr::deref() const
{
	auto p=check(curr,"deference past end");
	return (*p)[curr];
}
StrBlobPtr& StrBlobPtr::incr()
{
	check(curr,"increment past end of StrBlobPtr");
	++curr;
	return *this;
}
StrBlobPtr StrBlob::begin()
{
	return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
	auto ret=StrBlobPtr(*this,data->size());
	return ret;
}